          SUBROUTINE (PN,OID,GEN,QSIGN,LDID,QTY,VIEW.ONLY,PRC.KEY,QTY.CHNG.OK,SCHED.ON,NEW.ORDER,LDID.LIST,LINE,LOG.MV,ERR.SKIPS,ERR.CODES,ERR.MSGS,KEY.LIST,GROUP,ACTION.REQD,FATAL.ERR,QO,ALLOC.ZONE,ADDL.DATA,REDISP,LVL.LIST)
** Version# 105 - 03/07/2012 - 05:26pm - TRAVISC - main

*** Subroutine : OE.ADD.LINE.ITEM
*-------------------------------------------------------------------------*
*** This subroutine is the generic Eclipse subroutine to add a line item
*** on an order. You must have LED, OLED active and this routine will set
*** and use LD and OLD.LD. Also, if the PN passed in is 'C', then this
*** routine will add a stand-alone (line item) comment to the order.
*** If any errors are encountered in the addition
*** of the line item you will get them back in ERR.CODES with the
*** authorization key req'd to add the line item for that error (If it is
*** an auth key req'd) in KEY.LIST (of the same attb as the err in
*** ERR.CODES) This way the calling routine can handle all of the errors
*** at once and then recall this routine passing in ERR.SKIPS (attb delim
*** with the codes you have pre-atuh'd for this line item.
*-------------------------------------------------------------------------*
*** PN  - Eclipse PN to Add to the order (Should be "C" for cmt)   [IN]
*** OID - Eclipse Order ID we're adding this item to               [IN]
*** GEN - Generation you would like this item added to. If it's not
***     - available we will either create a new generation or add
***     - to exsisting generation with that avail date for item    [IN]
*** QSIGN - The qty sign of the order (-1 out of or 1 into stock)  [IN]
*** QTY  - Quantity to order of the PN on this order (as entered)  [IN]
*** LDID - Line item detail ID ("" => NEW, # => PN change on line) (IN/OUT)
***      - Must be "" and a new LDID gets created when adding a comment.
*** LDID - Line item detail ID ("" => NEW, # => PN change on line) (IN/OUT)
*** VIEW.ONLY - Whether this order is in view only mode or not     (IN)
*** PRC.KEY   - The level of price authorization the user has      [IN]
*** QTY.CHNG.OK - Whether the users allowed to change the item qty [IN]
*** SCHED.ON  - What level of auto scheduling is currently used    (IN)
*** NEW.ORDER - Whether this is a new order (never saved) or not   [IN]
*** LDID.LIST - VM Separated list of ldids for the order.          (IN/OUT)
*** LINE      - The line to add the new item into the ldid position(IN)
*** LOG.MV    - VM Separated list of gens update on the order      (IN/OUT)
*** ERR.SKIPS - VM Separated list of gens update on the order
***           - Attb 1 is the VM separated exception code list.
***           - Attb 2 is the data passed for the handled error code.
*** ERR.CODES - Attb delim list of errors/reasons we could not add
***           - This item to the order. See ERR.CODES section for
***           - a description of what each code number is.         (OUT)
*** ERR.MSGS  - Attb delim list to give an error description to the error
***           - code specified in the ERR.CODES array.             (OUT)
*** KEY.LIST  - Authorization key req'd to get through the error
***           - code in this attb of ERR.CODES                     (OUT)
*** GROUP     - Product group for this price branch/product        (OUT)
*** ACTION.REQD - If another pass after authorizations are made is
***             - required to add the line item onto the order     (OUT)
*** FATAL.ERR   - If this line item cannot be corrected to be added to
***             - order based on an unrecoverable error.           (OUT)
*** QO          - The parsed order qty after addition of the item  (OUT)
*** ALLOC.ZONE  - The zone to allocate the qty for the item        (IN)
*** ADDL.DATA   - Dual functionality:  For PN vs. "C".             (IN)
***             - For NUM(PN):
***             - Additional line item information to put into the LD
***             - array (AM separated to match the position in LD)
***             - For PN="C":
***             - ATTB <1> : VM list of comment types.
***             - ATTB <2> : VM list of comments, multi-lined by SVM.
*** REDISP      - Used in OE.PRICE.ITEM to redisplay all line items (IN)
***             - that contribute to group matrix pricing
*** LVL.LIST    - List (associated with KEY.LIST) to specifies what
***             - level the user must have of the associated auth
***             - key.  AM delimited.                               (OUT)
*-------------------------------------------------------------------------*
*** COMMON VARIABLES:
*** LED and OLED must be active before calling. You should also have a
*** lock on the record in the LEDGER file for this OID before calling this
*** routine. We will set and use LD, OLD.LD, PRD, PRD.BR, PRDP, PLNE, CUS,
*** CUSS, MA in this routine.
*-------------------------------------------------------------------------*
*** ERR.CODES :
*** 1 - Invalid PN Because of a bad sell/buy group        (Unrecoverable)
*** 2 - Old item was on an invoiced shipment              (Unrecoverable)
*** 3 - Invalid Lot Item (return)                         (Unrecoverable)
*** 4 - Invalid product at the specified branch           (Unrecoverable)
*** 5 - No order quantity specified. Second pass w/qo     (Recoverable)
*** 6 - Authorize use of an item under review             (Recoverable)
*** 7 - Product Certification Required  - One note on     (Recoverable)
***   - this authorization is that the certification info is passed out as
***   - a VM separated array to allow the authorization on all of the
***   - certifications at once from the calling subroutine.
*** 8 - Multiple customer part numbers, one needs selected (Recoverable)
*** 9 - Duplicate line item on the same order.            (Warning)
*** 10- Qty ordered entered was not valid.                (Unrecoverable)
*** 11- Not Currently Used
*** 12- Valid UOM must be selected...                     (Recoverable)
*** 13- Invalid Order Qty/Unit Of Measure Entered         (Recoverable)
*** 14- Different order qty sign than ship qty entered    (Unrecoverable)
*** 15- Sell below the minimum sell package qty.          (Recoverable)
*** 16- Invalid PIL effect (ERR.MSGS Stores the Data)     (Recoverable)
*** 17- Order Qty is greater than the inventory factor    (Recoverable)
*** 18- Buy package qty warning                           (Recoverable)
*** 19- Negative qty authorization required               (Recoverable)
*** 20- Delete status item on PO or SO without avail      (Recoverable)
*** 21- Tried to add purge item status                    (Unrecoverable)
*** 22- Duplicate order check needs authorization.        (Recoverable)
*** 23- A tag or direct item change authorization is req'd(Recoverable)
*** 24- A direct generation must be selected to add to    (Recoverable)
*** 25- Unable to successfully committ the quantities     (Unrecoverable)
*** 26- Reminder notes need displayed.                    (Note Window)
*** 27- If this item has subsitutes/add-on sell items
***   - 0 - No subs, 1 - This has subs, 2 - open subs window (Note)
*** 28- If this item is a nonstock this will be passed    (Note)
*** 29- Triggers for the item need to be displayed.       (Note)
*** 30- Auto price verification (quick price) needs opened(Note)
*** 31- Lot Billing Item - Open lot billing to edit.      (Note)
*** 32- Detail Lot Selection needs to be made             (Note)
*** 33- Line Item Scheduler Mode :                        (Note)
***   - 0 - No Scheduler Required
***   - 1 - Check user authorization/current auto mode
***   - 2 - Open the line item scheduler
*** 34- Return check required.                            (Note)
*** 35- Return type selection required, ERR.MSGS includes
***   - either the default return type, or the VM list of
***   - types to select from. The selected type needs to be
***   - sent through to the return check on the item.     (MenuTable)
*** 36- Other branches availability needs shown           (Note)
*** 37- POE Header for a direct must be shown. 2nd value of the message
***   - will contain the direct gen for the header        (Note)
*** 38- Credit message                                    (Note)
*** 39- Prompt user if they want to split qtys            (Recoverable)
*** 40- Quantity Breaks Need to Be Displayed              (Note Window)
*** 41- Line Item Taxability.  User must be prompted      (Prompt)
*** 42- Exceeded credit limit.  User must authorize.      (Prompt)
*** 43- rdc logic uesd in adding comments                 (Recoverable)
*** 44- Item is nonstock and user does not have auth      (Unrecoverable)
***   - to add nonstock items to order
*** 50- Custom Mod
*-------------------------------------------------------------------------*
          GOSUB INIT

          *** If this is not a new item, make sure the change is allowed.
          IF NOT(NEW.LD) THEN

             *** Check to see if this is a lot item, and was invoiced on
             *** any shipment (generation)
             IF LED(98)<1,GEN> = LDID THEN LOT.98=LDID ELSE LOT.98=0

             CT = DCOUNT(LED(9),VM)
             FOR G=1 TO CT
                INVN = LED(8)<1,G>
                IF NUM(LED(98)<1,G>) AND LOT.98 = LED(98)<1,G> THEN
                   IF LED(6)<1,G>='I' THEN
                      ALLOW.CHANGE = NO
                      ERR.CODES    = 2
                      ORDN         = OID:'.':INVN "R%3"
                      ERR.MSGS     = 'Lot Item on Invoice # : ':ORDN
                      FATAL.ERR    = YES
                      EXIT
                   END
                END
                SQTY = SUM(LD(5)<1,G>) + SUM(LD(6)<1,G>)
                IF G#GEN AND SQTY#0 AND INVN#'' THEN
                   ALLOW.CHANGE = NO
                   ERR.CODES    = 2
                   ERR.MSGS     = 'Item on Invoice # : ':OID:'.':INVN"R%3"
                   FATAL.ERR    = YES
                   EXIT
                END
             NEXT G

             *** Make sure the user is not affecting a tagged item or a
             *** direct...  But not if we've changed to the same PN.
             IF ALLOW.CHANGE AND LD(1) # PN THEN
                ERR.CODE = "23"
                *** Make sure this check was not already handled.
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                   OE.CHECK.FOR.TAG OID,GEN,-LD(4)*QSIGN,CHG.ERRS,NEW.ORDER,LDID,YES
                   *** Setup the error for editing a direct.
                   IF CHG.ERRS<1,1> THEN
                      ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = ERR.CODE
                      ERR.MSGS<ERR.POS>  = 'Change a Direct P/O'
                      KEY.LIST<ERR.POS>  = "SOE.DIRECT.EDIT"
                      UPDATE.OK          = NO
                   END

                   *** Setup the error for editing a tag quantity
                   IF CHG.ERRS<1,2> THEN
                      ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = ERR.CODE
                      ERR.MSGS<ERR.POS>  = "Delete a Tagged Qty"
                      KEY.LIST<ERR.POS>  = "OE.TAGGED.QTY.EDIT"
                      UPDATE.OK          = NO
                   END
                END
             END
          END ELSE
             * Don't let the user edit the costs on a MJB or Jr Order
             * w/o the proper authorizations...
             IS.JR     = LED(129)<1,1>
             IS.MJB    = LED(128)<1,1>
             KEY.REQD  = 'SOE.MASTER.BID.EDIT'
             CHECK.KEY KEY.REQD,,KEY.LEVEL
             IF (IS.MJB OR IS.JR) AND KEY.LEVEL < 4 THEN
                ERR.CODE = '53'
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   IF IS.MJB THEN
                      PRMPT = "Modify Order Qtys on a Master Job Bid"
                   END ELSE
                      PRMPT = "Modify Order Qtys on a Junior Order"
                   END

                   OE.MJB.AUTH.REQD OID,IS.AUTH.REQD
                   IF IS.AUTH.REQD THEN
                      ERR.MSGS<ERR.POS>  = PRMPT
                      KEY.LIST<ERR.POS>  = "SOE.MASTER.BID.EDIT"
                      UPDATE.OK          = NO
                   END
                END
             END

             MAT LD = ""
             IF PN  = "C" THEN GOTO CREATE.COMMENT
          END

          * Check to see if the product is available to sell at this branch
          READ PRD.REC FROM PRDFILE,PN ELSE PRD.REC = ""
          BR.ACC = PRD.REC<118>
          IF BR.ACC # "" THEN
             LOCATE SHIP.BR IN BR.ACC<1> SETTING POS ELSE
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = 4
                ERR.MSGS<ERR.POS>  = "Product not Available at this Branch"
                ALLOW.CHANGE       = NO
                FATAL.ERR          = YES
             END
          END

          *** If something was not valid in the previous checks, abort out
          IF NOT(ALLOW.CHANGE) THEN
             RETURN
          END

          P.STAT = PRD.REC<3>

          *** Do not allow the user to enter a return lot item
          IF P.STAT = 9 AND Q1 < 0 THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = 3
             ERR.MSGS<ERR.POS>  = 'Negative Lot Item Qtys Not Allowed'
             ALLOW.CHANGE       = NO
             FATAL.ERR          = YES
          END

          *** Do not allow the user to enter a lot item on a PO/Transfer
          IF P.STAT = 9 AND (MODE='P' OR MODE='T') THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = 3
             ERR.MSGS<ERR.POS>  = 'Lot Items Must Be Entered in Sales Order Entry'
             FATAL.ERR          = YES
             ALLOW.CHANGE       = NO
          END

          *** Do not allow a remote user to enter a lot item
          IF P.STAT = 9 AND REMOTE.CUST THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = 3
             ERR.MSGS<ERR.POS>  = "Remote Customers cannot Enter Lot Items"
             ALLOW.CHANGE       = NO
             FATAL.ERR          = YES
          END

          ** If the customer has exceeded the credit limit, user must
          ** authorize before being able to proceed with anything.
          LOCATE '42' IN ERR.CODES SETTING POS THEN
             ACTION.REQD = YES
             RETURN
          END

          *** If there was an unrecoverable error, ignore the rest.
          IF NOT(ALLOW.CHANGE) THEN
             UPDATE.OK = NO
             RETURN
          END

          GOSUB GET.PN

          *** Check again for unrecoverable error, ignore the rest.
          IF NOT(ALLOW.CHANGE) THEN
             UPDATE.OK = NO
             RETURN
          END

          GOSUB CHK.AUTO.PRC

          *** Make sure there were not any update errors before moving on.
          IF UPDATE.OK AND NOT(ERR) THEN

             IF PRC.BR=SHIP.BR THEN LOC.TYPE = PRD.BR(11) ELSE
                GET.PRD.BR.VAL SHIP.BR,PN,11,LOC.TYPE
             END
             IF LOC.TYPE = 'D' THEN
                GOSUB CHK.LOT
             END

             IF PRD(3) = 9 THEN
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = '31'
                ERR.MSGS<ERR.POS>  = 'Lot Item'
             END
          END

          *** Make sure an order qty was specified.
          IF QO = 0 AND VALID.ITEM THEN
             FOUND12 = 0; FOUND13 = 0
             LOCATE '12' IN ERR.CODES SETTING POS12 THEN FOUND12 = 1
             LOCATE '13' IN ERR.CODES SETTING POS13 THEN FOUND13 = 1
             *** handle order quantity before any others
             BEGIN CASE
             CASE FOUND12 AND NOT(FOUND13)
                ERR.CODES = INSERT(ERR.CODES,POS12+1;'5')
                ERR.MSGS  = INSERT(ERR.MSGS,POS12+1;'Order Quantity is Required':VM:'Press Return to Continue...')
                KEY.LIST  = INSERT(KEY.LIST,POS12+1;'')
             CASE FOUND13
                ERR.CODES = INSERT(ERR.CODES,POS13+1;'5')
                ERR.MSGS  = INSERT(ERR.MSGS,POS13+1;'Order Quantity is Required':VM:'Press Return to Continue...')
                KEY.LIST  = INSERT(KEY.LIST,POS13+1;'')
             CASE OTHERWISE
                ERR.CODES = INSERT(ERR.CODES,1;'5')
                ERR.MSGS  = INSERT(ERR.MSGS,1;'Order Quantity is Required':VM:'Press Return to Continue...')
                KEY.LIST  = INSERT(KEY.LIST,1;'')
             END CASE
             UPDATE.OK          = NO
             ACTION.REQD        = YES
             RETURN
          END

          *** Check for line item level user defined prompts (triggers)
          OID.DATA$<3> = LDID
          IF MODE = 'S' THEN
             ERR.CODE = '29'
             *** Make sure that triggers have not been prompted for.
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING POS ELSE
                OE.TRIGGER.GET.PROMPTS  9,OID,GEN,YES,LDID,SDATA,TR.DATA,DISP.DATA
                TCT = DCOUNT(RAISE(TR.DATA<1>), VM)

                *** If there are triggers to display, send the information
                *** to the client.
                IF TCT > 0 THEN
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = "Line Item Triggers."
                END
             END
          END

          GOSUB CHK.CUSTOM
          GOSUB CHK.SUB
          GOSUB CHK.SPLT

          *** Tell the client that this item's a nonstock item.
          IF PRD(3) = '2' THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = '28'
             ERR.MSGS<ERR.POS>  = ''
          END
          GOSUB COPY.IAO.CC
          RETURN
*-------------------------------------------------------------------------*
COPY.IAO.CC:*** Copying cogs to cost if it shoudl
            ***If the control record is set for copy COST to COGS for IAO
            ***item, we need to do it here. Note that we only do the copy
            ***if it is a sales order and the line item being updated is a
            ***new line item and of course, the product is IAO
          PRC.BR = LED(2)<1,GEN,1>
          IF MODE = 'S' AND NEW.LD AND LD(114) THEN
             READ COPY.IAO.COGS FROM CTRBFILE,"COPY.COST.TO.COGS.IAO~":PRC.BR ELSE COPY.IAO.COGS = ''
             IF COPY.IAO.COGS THEN
                LD(11)<1,GEN> = LD(10)<1,GEN>
                LD(10)<1,GEN> = LD(27)<1,GEN>
                OE.UPDATE.LDID LDID,OID,GEN,LOG.MV,QSIGN
             END
          END
          RETURN
*-------------------------------------------------------------------------*
CREATE.COMMENT: *
          OE.NEW.LDID OID,LDID

          LD(1)         = 'C'
          LD(2)         = ADDL.DATA<1>
          LD(3)         = ADDL.DATA<2>

          GEN.MV        = GEN
          UPDATE.LEDGER.DET OID,LDID,QSIGN,GEN.MV

          *** Make sure this gen is added to the log variable.
          LOCATE GEN IN LOG.MV<1> SETTING MV.POS ELSE
             LOG.MV = INSERT(LOG.MV,1,MV.POS;GEN)
          END

          ** The ldid insert in LED(49) can be removed iff
          ** UPDATE.LEDGER.DET updates LED(49) for comments correctly.
          LOCATE LDID IN LED(49)<1> SETTING POS ELSE
             LED(49) = INSERT(LED(49),1,POS;LDID)
          END

          RETURN
*-------------------------------------------------------------------------*
INIT:     *** Iinitialize all of the variables needed for this routine.
          U1            = ''
          Q1            = ''
          U2            = ''
          Q2            = ''
          QS            = ''
          QO            = ''
          QOPEN         = ''
          RET.SIGN      = ''
          FATAL.ERR     = NO
          VALID.ITEM    = NO
          MODE          = OID[1,1]
          SCHEDULE.ITEM = NO
          ALLOW.CHANGE  = YES
          ERR.CODES     = ""
          ERR.MSGS      = ""
          KEY.LIST      = ""
          UPDATE.OK     = YES
          ACTION.REQD   = NO
          REDISP        = ""
          NEW.LD        = (LDID = "")
          SHIP.BR       = LED(2)<1,GEN,2>
          PRC.BR        = LED(2)<1,GEN,1>
          SUB.REQD      = NO
          BT.CN         = LED(1)<1,GEN>
          ST.CN         = LED(5)<1,GEN>
          RET.TYP       = ''
          LVL.LIST      = ''
          IF NOT(ASSIGNED(ERR.SKIPS)) THEN ERR.SKIPS = ''
          SV.TAX        = (ERR.SKIPS = "")
          *** Treat rentals the same as sales orders.
          IF MODE = 'R' THEN MODE = 'S'

          *** Calculate the original open qty to make sure the right qtys
          *** committed on this change.  BUT, if we are changing PN's, then
          *** by definition, QOPEN is going to be 0.
          IF NOT(NEW.LD) AND NUM(PN) THEN
             OE.CALC.QOPEN OID,QSIGN,QOPEN,GEN
          END

          *** For sales orders check to make sure this customer's allowed
          *** to order this item.
          OE.OK   = YES
          IF MODE = 'S' THEN
          *** The host side logic for this is in full working order.
          *** Only need to worry about this for the client.
             IF JAVA.PROC$ THEN
                ERR.CODE = "42"
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING POS ELSE
                   SOE.CHECK.NO.OE BT.CN,ST.CN,OE.OK,USR.AUTH.ND,PRMPT
                   IF NOT(OE.OK) OR USR.AUTH.ND THEN
                      ECT = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ECT> = ERR.CODE
                      ERR.MSGS<ECT>  = "Allow Order Entry"
                      KEY.LIST<ECT>  = "SOE.CREDIT.RELEASE"
                      UPDATE.OK      = NO
                   END
                END
             END ELSE
                DO.CHK = YES
                IS.INV = NO
                IF NOT(LED(8)<1,GEN>) THEN
                   IS.INV = YES
                   STK.BR = LED(2)<1,GEN,2>
                   CTRB.ID = 'SOE.INV.CREDIT.CHECK~':STK.BR
                   READV DO.CHK FROM CTRBFILE,CTRB.ID,1 ELSE DO.CHK = NO
                END
                IF DO.CHK THEN
                   SOE.CREDIT.CHECK ST.CN,NO.OE,,,NO.SHIP
                   DO.IT  = NO
                   BEGIN CASE
                   CASE IS.INV AND (NO.OE OR NO.SHIP)
                      DO.IT  = YES
                   CASE IS.INV AND NOT(NO.OE)
                      ERR.POS              = DCOUNT(ERR.SKIPS<1>,VM) + 1
                      ERR.SKIPS<1,ERR.POS> = '99'
                   CASE NOT(IS.INV) AND NO.OE AND NOT(NO.OE.OVRD$)
                      DO.IT  = YES
                   END CASE
                   IF DO.IT THEN
                      IF NOT(CUSS(23)<1,5>) THEN
                         ERR.CODE = '51'
                         LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                            ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                            ERR.CODES<ERR.POS> = '51'
                            ERR.MSGS<ERR.POS>  = RET.TYP
                         END
                      END ELSE
                         OE.OK = NO
                      END
                   END
                END
                IF NOT(OE.OK) THEN UPDATE.OK = NO
             END
          END

          *** Setup the selected units of measure and qty's associated
          PARSE.QTY QTY,Q1,U1,Q2,U2

          *** Read the substitute information from the relevant controls
          READV AUTO.DISP.MSG FROM CTRLFILE,'AUTO.ADD.OE.MSG',1 ELSE
             AUTO.DISP.MSG = ""
          END

          IF MODE # 'P' THEN
             REC.NAME = 'AUTO.OE.SUBS'
          END ELSE
             REC.NAME = 'AUTO.POE.SUBS'
          END
          READV AUTO.SUB FROM CTRLFILE,REC.NAME,1 ELSE AUTO.SUB=''
          READV SUB.TYPE FROM CTRLFILE,'AUTO.OE.SUBS.TYPE',1 ELSE
             SUB.TYPE = ""
          END

          *** Setup the user flags for what PIL levels to check.
          READV NEW.PIL FROM CTRLFILE,'SOE.NEW.PIL.CHECK',1 ELSE NEW.PIL=''
          READV DIR.PIL FROM CTRLFILE,'SOE.DIR.PIL.CHECK',1 ELSE DIR.PIL=''
          READV CRD.PIL FROM CTRLFILE,'OE.RETURN.PIL.CHK',1 ELSE CRD.PIL=''

          *** Determine the setting for whether to show other branches
          *** availability or not.
          IF MODE = 'S' THEN
             CTRB.ID = 'AUTO.OE.SHOW.AVAIL~':SHIP.BR
             READV SHOW.AVAIL FROM CTRBFILE,CTRB.ID,1 ELSE SHOW.AVAIL = ''
          END


          READ NODISP.TYPS FROM CTRLFILE,'RETURN.PROD.TYPES' ELSE
             NODISP.TYPS = ''
          END

          READ PRD.TYPS FROM CTRLFILE,'PROD.STATUS' ELSE PRD.TYPS = ''


          *** Build arrays to save the common variables.
          MATBUILD SV.LD     FROM LD
          MATBUILD SV.LED    FROM LED
          MATBUILD SV.OLED   FROM OLED
          MATBUILD SV.OLD.LD FROM OLD.LD
          RETURN
*-------------------------------------------------------------------------*
GET.PN:   *** Retrieve all of the item information to add.
          ERR = NO

          *** If the item changed or is added, then we need to check for
          *** default direct shipment.
          IF LD(1) # PN THEN
             CHECK.DIR = YES
          END ELSE
             CHECK.DIR = NO
          END

          *** Verify that the user is authorized to change the qty on the
          *** Original line item.
          ERR.CODE = "16"
          IF NOT(NEW.LD) THEN
             IF QTY.CHNG.OK AND LD(1) # PN AND LED(6)<1,GEN> # 'B' THEN
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                   REP.PN  = YES
                   SV.PN   = PN;      PN      = LD(1)
                   SV.CRD  = CRD.PIL; CRD.PIL = NO
                   SV.QO   = QO
                   QO      = -(SUM(LD(5)<1,GEN>) + SUM(LD(6)<1,GEN>))
                   GOSUB CHK.PILS
                   REP.PN  = NO
                   PN      = SV.PN
                   CRD.PIL = SV.CRD
                   QO      = SV.QO
                   ERR     = NOT(PIL.OK)
                   IF ERR THEN
                      *** If the user could not authorize the effect
                      *** on PIL do not add the item onto the order
                      ALLOW.CHANGE = NO
                      FATAL.ERR    = YES
                      RETURN
                   END
                END
             END
          END

          OE.GET.PN OID,GEN,PRC.BR,PN,LDID,QSIGN,GROUP,ERR.CODES,KEY.LIST,ERR.MSGS,ERR.SKIPS

          IF ERR.CODES # "" THEN
             *** Make sure that no fatal errors were encountered.
             LOCATE '1' IN ERR.CODES SETTING POS THEN
                FATAL.ERR = YES
             END ELSE
                LOCATE '2' IN ERR.CODES SETTING POS THEN
                   FATAL.ERR = YES
                END
             END
             UPDATE.OK = NO
          END

          PRICE.PER.GET PER,,,,LED(22)<1,GEN>
          IF LED(92)<1,GEN,2> THEN PER=PER/OCONV(LED(92)<1,GEN,2>,'MR4')

          VALID.ITEM = YES

          *** Create the new ledger detail record to add onto the order.
          IF NEW.LD THEN
             OE.NEW.LDID OID,LDID,LDID.LIST,LINE
          END

          * Check to see if the user is authorized to add a nonstock item
          * to the order base on their auth key
          ERR.CODE = "44"
          IF (NEW.LD) THEN
             SV.QTY.OK = QTY.CHNG.OK

             * Get the auth key
             OE.GET.KEYS OID,GEN,NEW.ORDER,VIEW.ONLY,,QTY.KEY

             * Check to see if they may change the quantity (add the item)
             OE.QTY.CHNG.OK OID,GEN,QTY.KEY,VIEW.ONLY,QTY.CHNG.OK

             * If this is not a new order and the user does not have the
             * necessary quantity key, they may not add the line item
             IF (NOT(NEW.ORDER) AND NOT(QTY.CHNG.OK)) THEN
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = ERR.CODE
                ERR.MSGS<ERR.POS>  = "You are not authorized to add a nonstock item to this order."
                ALLOW.CHANGE = NO
                PRD.ERR      = YES
                UPDATE.OK    = NO
                FATAL.ERR    = YES
             END

             QTY.CHNG.OK = SV.QTY.OK
          END

          *** Check for duplicate products on the current order
          ERR.CODE = '9'
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
             READV CHK.DUP FROM CTRLFILE,'OE.DUP.ITEM.CHECK',1 ELSE CHK.DUP=''
             IF CHK.DUP AND NOT(PRD(127)) AND PRD(3) # 9 THEN
                OE.CHK.DUP.LINE.ITEMS OID,GEN,LDID,'S',DUP.LN
                IF DUP.LN > 0 THEN
                   DESC = PRD.REC<1>
                   MSG = 'PN#':LD(1):' : ':DESC[1,30]:' : already on Order on Line # ':DUP.LN
                   ERR.POS = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = MSG
                END
             END
          END

          *** If there was additional line item information, setup LD
          IF ADDL.DATA # '' THEN
             TCT = DCOUNT(ADDL.DATA,AM)
             FOR J = 2 TO TCT
                IF ADDL.DATA<J> THEN LD(J) = ADDL.DATA<J>
             NEXT J
          END

          * If the user is replacing the line item, set QO to LD(4) (to
          * emulate the user entering a quantity ordered) and then clear
          * the value in LD(4).
          IF OLD.LD(1)#'' AND OLD.LD(1)#LD(1) THEN
             QO    = LD(4) * QSIGN
             LD(4) = ''
             QOPEN = ''
          END

          *** Verify that the qty entered is valid.
          GOSUB CHK.QO

          *** Check for an existing order with this line item on it.
          *** Don't check for duplicate lot billing items.
          IF (MODE='S') AND (QO > 0) AND PRD(3) # "9" THEN
             ERR.CODE = "22"
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                IF PRD(3) # 9 THEN
                   SOE.CHK.DUP.ORDER OID,GEN,DUP.OK,OID.LIST,GEN.LIST,YES
                   IF NOT(DUP.OK) THEN
                      ID.LISTS = LOWER(OID.LIST):AM:LOWER(GEN.LIST)
                      AUTH.KEY = "SOE.AUTH.DUP.ORDER"
                      ERR.POS  = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = ERR.CODE
                      ERR.MSGS<ERR.POS>  = LOWER(ID.LISTS)
                      KEY.LIST<ERR.POS>  = AUTH.KEY
                      UPDATE.OK          = NO
                   END
                END
             END
          END

          *** If this item was added to the order add the ldid to the list
          UPD.LDID.LIST                    = YES
          IF PRD(3) = 9 AND LED(8)<1,GEN> THEN
             TQTY                 = SUM(LD(5)<1,GEN>) + SUM(LD(6)<1,GEN>)
             IF NOT(TQTY) THEN
                UPD.LDID.LIST              = NO
             END
          END
          IF UPD.LDID.LIST AND QO#0 THEN LDID.LIST<1,LINE> = LDID

          *** Verify this is not an invalid product
          GOSUB INVAL.PRDCHK
          *** If the product could not be added to the order we should
          *** just get out.
          IF FATAL.ERR THEN
             RETURN
          END

          *** Add the comment for change log as and audit trail.
          IF OLD.LD(1)#'' AND OLD.LD(1)#LD(1) THEN
             IF NEW.ORDER THEN
                *** figure out whether to log the changes based off the
                *** control record.
                READ LOG.PRD.CHG FROM CTRLFILE,'OE.LOG.PRD.CHNGS' ELSE LOG.PRD.CHG = ''
             END ELSE
                LOG.PRD.CHG = YES
             END
             IF LOG.PRD.CHG THEN
                READV ODESC FROM PRDFILE,OLD.LD(1),1 ELSE ODESC = OLD.LD(1)
                CMT        = '** Changed Product on Line Item - ':LDID
                CMT<1,1,-1> = 'From : ':ODESC<1,1> "L#30"
                CMT<1,1,-1> = 'To   : ':PRD(1)<1,1> "L#25"
                CMT = LOWER(CMT)
                OE.ADD.COMMENT OID,LOG.MV,CMT
            END
          END

          *** Update the qty to ship for this line item.
          ORIG.QTY = ''
          IF QO+0#0 THEN
             ORIG.QTY = LD(4)
             GOSUB UPD.QO
             GOSUB CHECK.DELETE.ITEM
          END

          GOSUB UPD.LINE.FGHT

          *** Only show the reminder messages when the item was added on.
          IF UPDATE.OK THEN
             *** Retrieve all reminder messages for this item.
             GOSUB GET.REMINDER
          END

          *** Only do for returns when item is added onto the order so we
          *** will have a valid LDID
          GOSUB CHK.NO.DISP.TYPS
          IF MODE='S' AND QO+0 < 0 AND NOT(NO.DISP.TYPE) AND UPDATE.OK THEN
             GOSUB CHK.RET   ;* Find all valid return types

             *** Pass back either the default type, or the types to
             *** select from to the client so that the selected type can
             *** be passed into the return check and validation.
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = '35'
             ERR.MSGS<ERR.POS>  = RET.TYP

             ERR.POS += 1
             ERR.CODES<ERR.POS> = '34'
             ERR.MSGS<ERR.POS>  = ORIG.QTY
          END

          RETURN
*-------------------------------------------------------------------------*
CHECK.DELETE.ITEM: * Remove a line item if it put the cust over the credit
                   * limit.
          * Do this check only once.
          ERR.CODE = '98'
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING ERRPOS THEN RETURN

          ERR.CODE = '99'
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING ERRPOS ELSE RETURN

          SOE.CREDIT.CHECK ST.CN,NO.OE
          IF NOT(NO.OE)                                  THEN RETURN

          * Log that we've done this routine.
          ERR.POS              = DCOUNT(ERR.SKIPS<1>,VM) + 1
          ERR.SKIPS<1,ERR.POS> = '98'

          IF NOT(CUSS(23)<1,5>) THEN
             ERR.CODE = '51'
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = '51'
                ERR.MSGS<ERR.POS>  = RET.TYP
             END
          END
          RETURN

          IF OE.OK THEN RETURN
          OE.DEL.LINE OID,GEN,LDID,,,,,QSIGN,,LOG.MV

          RETURN
*-------------------------------------------------------------------------*
CHK.QO:   *** Verify that a valid qty and UM were entered for this item.
          SV.QO = QO

          *** If there are unit's of measure defined at the product level
          *** use them, otherwise, just use the price lines.
          IF PRD(15) = '' THEN
             UM.TBL = PLNE(3)
          END ELSE
             UM.TBL  = PRD(15)
          END

          *** QO is returned as the quantity ordered in its lowest
          *** unit of measure...
          VALIDATE.SELL.UM MODE,UM.TBL,PRD(7),Q1,U1,Q2,U2,1,VER,QO,,,,YES,SEL.REQD
          IF SEL.REQD THEN
             ERR.CODES = INSERT(ERR.CODES,1;'12')
             ERR.MSGS  = INSERT(ERR.MSGS,1;'Valid UM Required')
             KEY.LIST  = INSERT(KEY.LIST,1;'')
             UPDATE.OK = NO
          END

          QO = QO + 0

          *** Don't allow the update to proceed if there are not qtys defined for the unit of measure.
          IF ERR = 2 THEN
             PROD.DESC = PRD(1)
             CONVERT VM TO ' ' IN PROD.DESC
             MSG = 'PN#':PN"L#7":': ':PROD.DESC"L#30":VM:'No quantities defined for unit of measure entered!.':VM:'Press Return to Continue...'
             QO = 0
             LOCATE '12' IN ERR.CODES SETTING POS12 THEN
                ERR.CODES = INSERT(ERR.CODES,POS12+1;'13')
                ERR.MSGS  = INSERT(ERR.MSGS,POS12+1;MSG)
                KEY.LIST  = INSERT(KEY.LIST,POS12+1;'')
             END ELSE
                ERR.CODES = INSERT(ERR.CODES,1;'13')
                ERR.MSGS  = INSERT(ERR.MSGS,1;MSG)
                KEY.LIST  = INSERT(KEY.LIST,1;'')
             END
             UPDATE.OK          = NO
             RETURN
          END

          *** Verify that the user has not changed the sign on an item that
          *** been split shipped.
          IF QO THEN
             IF SV.QO/QO < 0 THEN
                IF LD(4)#(SUM(LD(5)<1,GEN>)+SUM(LD(6)<1,GEN>)) THEN
                   MSG      = 'Multiple Ship Qtys - Cannot Reverse Sign'
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = 14
                   ERR.MSGS<ERR.POS>  = MSG
                   UPDATE.OK          = NO
                   FATAL.ERR          = YES
                   QO = SV.QO
                   ERR = YES
                   RETURN
                END
             END
          END

          * Check control record to determine if the quantity must be
          * in multiples of the sell package quantity on return items.
          CTRL.ID  = "MIN.PACKAGE.RETURNS"
          READV REQ.RET FROM CTRLFILE,CTRL.ID,1 ELSE REQ.RET = ""
          QO.OK    = ((QO > 0) OR (QO < 0 AND REQ.RET))

          * Save the return sign for later use.
          IF QO # 0 THEN
             RET.SIGN = (QO / ABS(QO))
          END
          IF MODE = 'S' THEN
             GOSUB CHECK.RET
             IF RET.ERR THEN
                RETURN
             END
          END

          *** Verify that the qty does not fall below a sell package break
          IF ((MODE = 'S') AND (PRD.BR(1) > 1) AND QO.OK) THEN
             ERR.CODE = 15
             MIN.PCK  = PRD.BR(1)
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING ERR.POS THEN
                ACTION.OK = ERR.SKIPS<2,ERR.POS> + 0
                IF NOT(ACTION.OK) THEN
                   QO = (MIN.PCK * (INT(QO / MIN.PCK) + 1)) * RET.SIGN
                END
                PRICE.PER.GET PER,,,,LED(22)<1,GEN>
                IF LED(92)<1,GEN,2> THEN PER=PER/OCONV(LED(92)<1,GEN,2>,'MR4')
             END ELSE
                IF (QO.OK AND (INT(QO / MIN.PCK) # (QO / MIN.PCK))) THEN
                   IF LED(110)<1,1> = 'B' THEN CONSIGN = 1 ELSE CONSIGN = 0
                   IF CONSIGN THEN LVL.REQD = 1 ELSE LVL.REQD = 2
                   DFLT.PER.GET 'S',PER,ALPHA
                   AUTH.KEY = "SOE.PACKAGE.QTY"
                   MSG      = 'Sell Below Minimum Package Qty of ':MIN.PCK/PER:' ':ALPHA
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = MSG
                   KEY.LIST<ERR.POS>  = AUTH.KEY
                   LVL.LIST<ERR.POS>  = LVL.REQD
                   UPDATE.OK          = NO
!!! What to do with this
                   PRMPT.LOG = MSG:' with ':QO:' ^':PN:' ':PRD(1)<1,1>
                END
             END
          END

          *** Check the maximum days supply
          ERR.CODE = "16"
          IF LED(6)<1,GEN> # 'B' THEN
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING POS ELSE
                REP.PN = NO
                GOSUB CHK.PILS
                IF NOT(PIL.OK) THEN
                   PRD.DESC           = PRD(1)<1,1>:VM:PRD(1)<1,2>
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = PRD.DESC:VM:LOWER(ADDL.INFO)
                   KEY.LIST<ERR.POS>  = "OE.PIL.DAYS.OVRD"
                   UPDATE.OK          = NO
                END
             END
          END

          * Check for invoice overcommitments.
          IF (QO - QOPEN) > 0 AND MODE = 'S' AND LED(8)<1,GEN> THEN
             STK.BR = LED(2)<1,GEN,2>

             CTRB.ID = 'SOE.INV.AVAIL.CHECK~':STK.BR
             READV DO.CHK FROM CTRBFILE,CTRB.ID,1 ELSE DO.CHK = NO
             IF DO.CHK AND NOT(LED(33)<1,GEN>) THEN
                ERR.CODE = '50'
                AUTH.KEY = 'OE.OVERCOMMIT.STOCK'
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING POS ELSE
                   OE.CHECK.AVAIL OID,GEN,LDID,AV.DT,,,QO.DIFF,YES
                   IF AV.DT > DATE() THEN
                      PRMPT  = 'Overcommit - Available : '
                      PRMPT := OCONV(AV.DT,'D4/')
                      ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = ERR.CODE
                      ERR.MSGS<ERR.POS>  = PRMPT
                      KEY.LIST<ERR.POS>  = AUTH.KEY
                      UPDATE.OK          = NO
                   END
                END
             END

          END

          *** Check the order to inventory factor (from control file)
          IF (MODE = 'S') AND (LED(6)<1,GEN> # 'B') AND (LED(33)<1,GEN> = "") AND (QO > 0) AND (PRD(3)#3) AND (PRD(3)#6) THEN
             GOSUB INV.FACTOR

             *** If the inventory was overriden then make sure that the
             *** user is sent to the scheduler.
             IF INV.OVRD THEN
                SCHEDULE.ITEM = YES
             END
          END

          *** If they are in POE Check to make sure there's not a buy pkg
          *** conflict with the qty ordered on an item.
          IF MODE = 'P' AND QO > 0 THEN
             GOSUB CHK.PKG
          END

          *** Verify that the user has the authorization to enter a
          *** negative order for the order mode specified.
          IF MODE # 'W' THEN
             IF QO < 0 THEN
                ERR.CODE = "19"
                LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                   AUTH.KEY = MODE:'OE.CREDIT.QTY'
                   CHECK.KEY AUTH.KEY,CRED.OK
                   IF NOT(CRED.OK) THEN
                      PRMPT = 'Issue a Negative Quantity On a Sales Order'
                      ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = ERR.CODE
                      ERR.MSGS<ERR.POS>  = PRMPT
                      KEY.LIST<ERR.POS>  = AUTH.KEY
                      UPDATE.OK          = NO
                   END
                END
             END
          END
          *** Check for deleted status and stock levels authorization
          ERR.CODE = "20"
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
             ERR      = NO
             ERR.MSG  = ""
             QO.DIFF  = QO - QOPEN

             IF OLD.LD(1) = LD(1) THEN
                Q.ORD = QO.DIFF
             END ELSE
                Q.ORD = QO
             END

             OE.CHK.DEL OID,GEN,SHIP.BR,PN,QSIGN,GROUP,Q.ORD,ERR.MSG,YES
             IF ERR.MSG THEN
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = ERR.CODE
                ERR.MSGS<ERR.POS>  = ERR.MSG
                KEY.LIST<ERR.POS>  = "OE.PRODUCT.USE.DELETE"
                UPDATE.OK          = NO
             END
          END

          *** Check for purge status; if so, delete the entire line
          IF PRD(3) = 7 THEN
             ERR.CODE = "21"
             MSG      = 'Item in Purge Status. Can not add to order.'
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = MSG
             UPDATE.OK          = NO
             FATAL.ERR          = YES
             RETURN
          END

          LD(23) = U1
          READ ORD.UOM FROM CTRLFILE,'OE.USE.ORDER.UOM' ELSE ORD.UOM=''
          IF ORD.UOM THEN
             LD(85) = U1
          END

          LD(41) = ALLOC.ZONE

          *** If Misc Charge Item, Exclude from Sales index.
          IF PRD(3)=3 THEN
             LD(42)<1,1> = 1
          END ELSE
             LD(42)<1,1> = ''
          END

          RETURN
*-------------------------------------------------------------------------*
UPD.QO:   *** Update the order qty on the line item.
          QO.DIFF = QO - QOPEN

          *** If the qty was lowered check to make sure a tag or direct
          *** qty has not been adversely effected.
          IF QO.DIFF<0 THEN
             ERR.CODE = "23"
             *** Make sure this check was not already handled.
             LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS ELSE
                OE.CHECK.FOR.TAG OID,GEN,QO.DIFF,CHGS,NEW.ORDER,LDID,YES
                *** Setup the error for editing a direct.
                IF CHGS<1,1> THEN
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = 'Change a Direct P/O'
                   KEY.LIST<ERR.POS>  = "SOE.DIRECT.EDIT"
                   UPDATE.OK          = NO
                END

                *** Setup the error for editing a tag quantity
                IF CHGS<1,2> THEN
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = "Delete a Tagged Qty"
                   KEY.LIST<ERR.POS>  = "OE.TAGGED.QTY.EDIT"
                   UPDATE.OK          = NO
                END
             END
          END

          *** Don't continue to commit the qty's if no update's allowed
          IF NOT(UPDATE.OK) THEN GOTO NO.UPD

          *** Setup the order qty on the ledger detail information.
          LD(4) = LD(4) + QO.DIFF*QSIGN
          QOPEN = QO

          *** Setup the total order qty for this line item.
          IF MODE='T' THEN
             *** Transfers only have on ship and one receive gen, don't
             *** double the qty by adding both of those as the order qty
             TOL.QTY = (SUMMATION(LD(5)<1,1>)+SUMMATION(LD(6)<1,1>))*QSIGN
          END ELSE
             *** On all other order types the total qty is all shipments.
             TOL.QTY = (SUMMATION(LD(5))+SUMMATION(LD(6)))*QSIGN
          END

          *** If open qty changed sign, clear all previous scheduling
          *** Note : this will cause problems if some gens are gl closed!
          IF (TOL.QTY<0 AND QOPEN>0) OR (TOL.QTY>0 AND QOPEN<0) THEN
             LD(5) = ''
             LD(6) = ''
             LD(7) = ''
          END

          *** Verify whether this item is committed on a direct
          OLD4          = LD(4)
          DIR.COMMITTED = NO
          IF MODE='S' AND CHECK.DIR AND PRD(105)<1,1> THEN
             GOSUB LOAD.DIR
             IF NOT(UPDATE.OK) THEN
                GOTO NO.UPD
             END
          END

          *** Verify that this item has not been committed on a direct.
          IF NOT(DIR.COMMITTED) THEN
             *** Check to fulfill the qty's for a dynamic kit.
             IF PRD(106) AND LED(6)<1,GEN>#"B" THEN
                OE.GET.DKIT.COMPS OID,GEN,SHIP.BR,PN,LDID
             END

             *** Committ the quantities
             OE.COMMT.QTYS OID,LDID,QSIGN,GEN
          END

          QS = (SUM(LD(5)<1,GEN>)+SUM(LD(6)<1,GEN>)) * QSIGN

          *** Log a UET Event for adding the order qty.
          UET.ENABLED = NO
          IF UET.ENABLED$ THEN
             CTRB.ID = 'UET.ENABLED~':LED(2)<1,GEN,2>
             READV UET.ENABLED FROM CTRBFILE,CTRB.ID,1 ELSE UET.ENABLED=NO
          END
          IF UET.ENABLED AND LED(6)<1,GEN> # "B" THEN
             ORD.QTY = LD(4) * QSIGN
             IF MODE='S' AND (PRD(3)=1 OR PRD(3)=2) AND ORD.QTY > 0 AND NOT(LED(33)<1,GEN>) AND NOT(OLD.LD(4)) THEN
                GOSUB LOG.UET
             END
          END

          *** If the qty's were not commmitted properly, show the error.
          TQS = (SUMMATION(LD(5))+SUMMATION(LD(6))) * QSIGN
          IF MODE#'T' AND LD(4)*QSIGN # TQS THEN
             LD(4) = TQS*QSIGN
             QO    = TQS
             QOPEN = TQS
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = "25"
             ERR.MSGS<ERR.POS>  = "Unable to committ order quantities."
             FATAL.ERR          = YES
             UPDATE.OK          = NO
          END

          *** Only update the line item if there were not any errors.
          IF UPDATE.OK THEN
             *** Log abc line item change or cancel
             ABC.ENABLED = NO
             IF ABC.ENABLED$ THEN
                CTRB.ID = 'ABC.ENABLED~':LED(2)<1,GEN,2>
                READV ABC.ENABLED FROM CTRBFILE,CTRB.ID,1 ELSE
                   ABC.ENABLED = NO
                END
             END
             IF ABC.ENABLED AND NOT(NEW.ORDER) THEN
                OE.ABC.UPD.LINE LDID,OID,GEN
             END

             *** If this item was not updated on a direct, update it
             IF NOT(DIR.COMMITTED) THEN
                GOSUB PRC.ITEM

                *** Calculate the original line item freight factor.
                IF MODE = "P" AND NOT(LD(34)<1,GEN>) AND LD(4) > 0 THEN
                   GOSUB CALC.FF
                END

                *** Return the remnant qty information for display.
                OE.DISP.RMNT OID,GEN,DLINE,QSIGN

                *** Update the line item information.
                GOSUB UPD.LINE

                *** Check to see if the line item scheduler should open
                GOSUB CHECK.SCHEDULE
             END

             *** Return any additional branch avail inventory
             IF MODE = 'S' THEN
                GOSUB VIEW.BR.INVS
             END
          END ELSE
NO.UPD:      *** Don't make the update, just return the required errors.
             PRDD.BR.UNLOCK SHIP.BR,LD(1)

             ACTION.REQD = YES

             *** Reload all of the global variables
             MATPARSE LD     FROM SV.LD
             MATPARSE LED    FROM SV.LED
             MATPARSE OLED   FROM SV.OLED
             MATPARSE OLD.LD FROM SV.OLD.LD
          END
          * When we are updating the line item, we need to make sure to
          * update the group quantities, because split quantity pricing
          * may have caused the amount being ordered on the current line
          * to change, and this must be taken into consideration.
          IF QSIGN = 1 THEN GROUP = PRD.BR(23) ELSE GROUP = PRD.BR(24)
          OE.UPD.GROUP GEN,LDID,QSIGN,GROUP

          RETURN
*-------------------------------------------------------------------------*
UPD.LINE: *** Update the line item information on the order.
          IF NOT(VIEW.ONLY) THEN
             IF PRC.KEY = 2 THEN
                IF LD(8)<1,GEN> # OLD.LD(8)<1,GEN> THEN
                   GOSUB SET.PRC.EXPIRE
                END
             END

             *** Log abc line item change or cancel *
             ABC.ENABLED = NO
             IF ABC.ENABLED$ THEN
                CTRB.ID = 'ABC.ENABLED~':LED(2)<1,GEN,2>
                READV ABC.ENABLED FROM CTRBFILE,CTRB.ID,1 ELSE
                   ABC.ENABLED = NO
                END
             END
             IF ABC.ENABLED AND NOT(NEW.ORDER) THEN
                OE.ABC.UPD.LINE LDID,OID,GEN
             END

             *** OE.VIEW.DATA$<12> is a flag to redisplay order
             *** lines if subtotals are affected by line change.
             OE.UPDATE.LDID LDID,OID,GEN,LOG.MV,QSIGN,LDID.LIST

             *** Calls Stock Availability Service Level Tracking Subroutine
             SOE.UPDATE.STOCK.SL OID,LDID,,MODE,1

             * Don't auto-check for credit limit on invoiced gens
             IF MODE='S' AND NOT(LED(8)<1,GEN>) THEN
                GOSUB CHK.CRED
             END
          END
          RETURN
*-------------------------------------------------------------------------*
SET.PRC.EXPIRE: *
          OE.SET.PRICE.EXPIRE OID
          RETURN
*-------------------------------------------------------------------------*
PRC.ITEM: OE.PRICE.ITEM OID,GEN,LDID,PN,QO,QSIGN,GROUP,LOG.MV,REDISP,LDID.LIST,DLINE.XREF,VIEW
          RETURN
*-------------------------------------------------------------------------*
CHK.CRED: **** Check the customers credit params
          CRED.ERR  = NO
          CLIM.MESS = ''
          IF MODE#'S' THEN RETURN

          SOE.CREDIT.CHECK ST.CN,NO.OE,COD,,NO.SHIP,LED(76),MSG,OID,GEN,CLIM.MESS
          IF NOT(VIEW.ONLY) AND (NO.SHIP OR NO.OE) THEN
             ABC.ENABLED = NO
             IF ABC.ENABLED$ THEN
                CTRB.ID = 'ABC.ENABLED~':LED(2)<1,GEN,2>
                READV ABC.ENABLED FROM CTRBFILE,CTRB.ID,1 ELSE
                   ABC.ENABLED = NO
                END
             END
             IF ABC.ENABLED AND MODE = 'S' THEN
                ACD = 'COAHOLD'
                *** Check that this invoice has not already been logged
                *** for credit hold
                LOCATE ACD IN LED(120)<1> SETTING XX ELSE
                   LED(120)<1,-1> = ACD
                   GOSUB SET.DATA
                   GOSUB LOG.ABC
                END
             END
          END
          OE.OK = YES
          USR.AUTH.ND = NO
          IF NOT(VIEW.ONLY) AND NO.OE AND OE.OK#2 THEN
             SOE.CHECK.NO.OE BT.CN,ST.CN,OE.OK,USR.AUTH.ND
          END

          IF NOT(OE.OK) THEN
             FATAL.ERR = YES
          END
          *** User must authorize the credit release on the client
          IF NOT(OE.OK) OR USR.AUTH.ND AND JAVA.PROC$ THEN
             ECT = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ECT> = "42"
             ERR.MSGS<ECT>  = "Allow Order Entry"
             KEY.LIST<ECT>  = "SOE.CREDIT.RELEASE"
             UPDATE.OK      = NO
          *** Setup the credit message to pass back.
          END ELSE IF TRIM(MSG)#"" THEN
             CRED.ERR           = YES
             ERR.CODE           = "38"
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = MSG
          END
          RETURN
*-------------------------------------------------------------------------*
INV.FACTOR: *** Check to make sure that inventory factor is not effected
            *** more than the product is setup.
          INV.ERR = NO; INV.OVRD = NO; CHK.ORD.FAC = NO

          *** Make sure that this error was not already handled
          ERR.CODE = "17"
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS THEN
             INV.OVRD = YES
          END ELSE

             *** If there's an order to inventory factor defined check it.
             *** first at the product and then with the control record.
             ORD.INV.FAC = PRD.REC<122>
             IF LED(110)<1,1>#'B' AND ORD.INV.FAC# '' AND QO#0 THEN
                CHK.ORD.FAC = YES
             END ELSE
                IF LED(110)<1,1>#'B' AND ORD.INV.FACTOR$#'' AND QO#0 THEN
                   CHK.ORD.FAC = YES
                END
             END

             IF CHK.ORD.FAC THEN
                CALC.AVAIL STK.LEVEL,LED(4)<1,GEN>,SHIP.BR,PN

                *** If there is no onhand then don't check this product
                IF STK.LEVEL <= 1 THEN GOTO SKIP.FAC

                INV.FCTR   = (QO/STK.LEVEL)*100
                IF ORD.INV.FAC THEN
                   ALLOW.FCTR = OCONV(ORD.INV.FAC,'MR2')
                END ELSE
                   ALLOW.FCTR = OCONV(ORD.INV.FACTOR$,'MR2')
                END
                IF ALLOW.FCTR = 0 THEN GOTO SKIP.FAC

                *** If the actual % is more than the defined % warn the user
                IF INV.FCTR > ALLOW.FCTR THEN
                   MSG = 'Order Qty is Greater than Inventory Factor of ':ALLOW.FCTR "R2#6":'%.'
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = MSG
                   UPDATE.OK          = NO
                END
             END
          END
SKIP.FAC: *
          RETURN
*-------------------------------------------------------------------------*
INVAL.PRDCHK: *** Check to make sure that all of the required product info
              *** Exists on the selected line item.

          PRD.ERR = NO
          READ GL.TYPES FROM CTRLFILE,'GL.PRODUCT.TYPE' ELSE GL.TYPES=''
          GL.ERR = NO                ;* Set GL Error variable to no

          *** If the site has valid GL Types, then make sure each product
          *** entered has a valid GL Type. If the site does not use GL Type
          *** Types, don't check for this when checking for Invalid Data.
          IF GL.TYPES<1> THEN
             IF PRD.REC<2> = '' THEN GL.ERR = YES ELSE GL.ERR = NO
          END ELSE
             GL.ERR = NO
          END

          *** GL.ERR = PRD.REC<2>: GL Types
          *** PRD.REC<7>: Unit of Measure
          *** PRD.REC<9>: Price Line
          IF GL.ERR OR PRD.REC<7> = '' OR PRD.REC<9> = '' THEN
             PROD.DESC = PRD(1)
             CONVERT VM TO ' ' IN PROD.DESC

             MSG = 'PN#':PN"L#7":': ':PROD.DESC"L#30":': Not Added. Invalid Product Data.'

             ERR.CODES<-1> = "1"
             ERR.MSGS<-1>  = MSG
             PRD.ERR       = YES
             UPDATE.OK     = NO
             FATAL.ERR     = YES
          END
          RETURN
*-------------------------------------------------------------------------*
CHK.PILS: *** Check the effect of the change on the projected inventory lvl
          PIL.OK = YES
          PIL.DIR.CHK = (MODE = 'S' AND LED(33)<1,GEN> AND DIR.PIL)

          *** Check the control file for the maximum days supply and make
          *** sure this will not put them over it
          IF MODE = 'S' AND NEW.ORDER AND NEW.PIL   THEN RETURN
          IF PIL.DIR.CHK                            THEN RETURN
          IF PRD(3) = 3 OR PRD(3) = 6 OR PRD(3) = 9 THEN RETURN

          *** Only check sales order that are returned.
          GOSUB CHK.NO.DISP.TYPS
          IF MODE = 'S' AND QO < 0 AND NOT(NO.DISP.TYPE) THEN
             *** If the item was replaced, don't perform the authorization.
             IF REP.PN  THEN RETURN
             *** If this is a credit pil, don't perform the authorization.
             IF CRD.PIL THEN RETURN

             *** Only check for non-direct orders.
             IF NOT(LED(33)<1,GEN>) AND LED(110)<1,1> # 'B' THEN
                GOSUB CHK.RET
                IF RET.TYP = 'F' THEN RETURN ;* Don't check PIL on defectiv
             END
          END

          *** Determine the change in the qty to check the effect on PIL
          BEGIN CASE
            CASE REP.PN
               SQTY = QO
            CASE SV.QO+0=0
               SQTY = QO * QSIGN
            CASE OTHERWISE
               SQTY = (SV.QO-QO)*-QSIGN
          END CASE

          *** If replacing a pn then check for authorization if PIL not ok
          IF REP.PN THEN NO.AUTH = NO ELSE NO.AUTH = YES

          *** Determine if the change requires authorization or not.
          OE.CHK.PIL OID,GEN,SHIP.BR,PN,SQTY,PIL.OK,ADDL.INFO,NO.AUTH

          RETURN
*-------------------------------------------------------------------------*
CHK.PKG:  *** Check the buy package qty for this product to make sure that
          *** the order qty is divisible by the package qty.
          IF MODE # 'P' THEN RETURN

          *** Make sure that this error was not previously handled.
          ERR.CODE = "18"
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS THEN RETURN

          *** Get the buy package for this branch.
          DFLT.PER.GET 'P',BPER,BALPHA

          PRD.BR.GET.VAL LED(2)<1,GEN,1>,LD(1),4,BUYPKG

          *** If there is not a buy package, make it 1.
          IF BUYPKG < 1 THEN
             BUYPKG = 1
          END

          *** Check that the Quantity on order is divisible by the pkg qty.
          IF MOD(QO,BUYPKG) # 0 THEN
             DIV = PRD.BR(27)
             IF DIV = 'O' THEN DIV = ''
             IF NOT(DIV) THEN
                DIV.MSG  = 'Product Has a Non-Divisible Buy Package of : '
             END ELSE
                DIV.MSG  = 'Product Has a Divisible Buy Package of : '
             END

             BPKG     = PERCONV(BUYPKG,BPER,0)
             DIV.MSG := BPKG:BALPHA "L#2"

             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = DIV.MSG
          END
          PRICE.PER.GET PER,,,,LED(22)<1,GEN>
          IF LED(92)<1,GEN,2> THEN PER=PER/OCONV(LED(92)<1,GEN,2>,'MR4')
          RETURN
*-------------------------------------------------------------------------*
LOAD.DIR: *** Determine whether this item's commited to a direct or not.

          *** Make sure that this user is authorized to enter a direct
          CHECK.KEY 'SOE.DIRECT.EDIT',ENTRY.OK
          IF NOT(ENTRY.OK) THEN RETURN

          *** If this is already a direct order, skip the commit checks.
          IF LED(6)<1,GEN> = 'D' THEN RETURN

          DIR.GENS   = ''
          DIR.GEN.ST = ''
          DGN.CT     = DCOUNT(LED(6),VM)

          *** Look for a direct generation to add the item to.
          FOR DGN = 1 TO DGN.CT
             IF LED(6)<1,DGN> = 'D' THEN

                *** Find s shipto that matches that of the item.
                LOCATE LED(33)<1,DGN> IN LED(12)<1> SETTING TGEN THEN
                   WRK = LED(5)<1,TGEN>
                END ELSE
                   WRK = ""
                END
                IF PRD(105)<1,2> = '' OR PRD(105)<1,2> = WRK THEN
                   DIR.GENS<1,-1> = 'Add to DIRECT Scheduled ':LED(9)<1,DGN>"D4/"
                   DIR.GENS<2,-1> = LED(12)<1,DGN>
                   IF PRD(105)<1,2> AND LED(9)<1,DGN>=LED(9)<1,GEN> THEN
                      DIR.GEN.ST = DCOUNT(DIR.GENS<1>,VM)
                   END
                END
             END
          NEXT DGN

          *** Determine whether a new direct gen should be created since
          *** there was not a direct with the proper vendor for the item
          IF DIR.GEN.ST = '' THEN
             DIR.GENS<1,-1> = 'Create New DIRECT'
             DIR.GEN.ST = DCOUNT(DIR.GENS<1>,VM)

             IF PRD(105)<1,2> THEN
                DIR.GENS<1,-1> = 'Create New DIRECT - Show PO Header'
             END
          END

          *** Allow the item to be shipped from stock instead of direct.
          DIR.GENS<1,-1> = 'Do NOT Ship Item DIRECT'

          ERR.CODE = "24"
          DIR.VEN = ''
          *** If the user has selected an option, use that...
          LOCATE ERR.CODE IN ERR.SKIPS<1> SETTING EPOS THEN
             SEL.GEN = ERR.SKIPS<2,EPOS>
             DIR.VEN = ERR.SKIPS<3,EPOS>
             GOSUB ADD.DIRECT
          END ELSE
             *** ...Otherwise, send the information to select back.
             SEL.DATA = DIR.GEN.ST:AM:DIR.GENS
             *** The host has no need to tack on the default vendor
             *** for this, so don't bother unless this runs on the client.
             IF JAVA.PROC$ THEN SEL.DATA := AM:PRD(105)<1,2>
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = LOWER(SEL.DATA)
             DIR.COMMITTED      = YES
             UPDATE.OK          = NO
          END
          RETURN
*-------------------------------------------------------------------------*
ADD.DIRECT:  *** Add the line item to the specified direct shipment.

          IF SEL.GEN = '' THEN RETURN
          IF SEL.GEN[1,1] = 'D' THEN RETURN
          MATBUILD SV.CUS  FROM CUS
          MATBUILD SV.CUSS FROM CUSS

          *** Create the new shipment to add the line item on.
          IF SEL.GEN[1,1] = 'C' THEN
             OE.CREATE.NEW.GEN NEW.GEN,OID,,LED(9)<1,GEN>,LED(2)<1,GEN,2>,GEN
             *** If there's a default vendor for the item, setup the direct
             *** DIR.VEN is passed back from Solar as the user selected
             *** vendor for products which do not have a default vendor
             *** assigned.
             IF PRD(105)<1,2> OR DIR.VEN # '' THEN
                IF NOT(DIR.VEN) THEN
                   SF = PRD(105)<1,2>
                END ELSE
                   SF = DIR.VEN
                END
                GET.PT.AP PT,SF

                MATBUILD SV.LD2     FROM LD
                MATBUILD SV.OLD.LD2 FROM OLD.LD

                OE.CREATE.DIRECT OID,NEW.GEN,PT,SF,DGEN,LOG.MV

                MATPARSE LD      FROM SV.LD2
                MATPARSE OLD.LD  FROM SV.OLD.LD2

                IF INDEX(SEL.GEN,'Show PO Header',1) THEN
                   ERR.CODE           = '37'
                   ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                   ERR.CODES<ERR.POS> = ERR.CODE
                   ERR.MSGS<ERR.POS>  = 'POE Header':VM:DGEN
                END
             END ELSE
                *** Otherwise, the user must specifiy it.
                OE.UPDATE.STATUS OID,NEW.GEN,QSIGN,LOG.MV,'D',ERR.MSG
                IF ERR.MSG THEN
                   OE.DEL.GEN OID,NEW.GEN
                   RETURN
                END

                *** Setup the new direct ship generation ID.
                LOCATE LED(33)<1,NEW.GEN> IN LED(12)<1> SETTING DGEN ELSE
                   DGEN = NEW.GEN
                END
             END
          END ELSE
             *** Setup the information for the shipment to add the item
             *** onto based on the users selection.
             LOCATE SEL.GEN IN DIR.GENS<1> SETTING X THEN
                LOCATE DIR.GENS<2,X> IN LED(12)<1> SETTING NEW.GEN ELSE
                   NEW.GEN = GEN
                END
                LOCATE LED(33)<1,NEW.GEN> IN LED(12)<1> SETTING DGEN ELSE
                   DGEN = NEW.GEN
                END
             END ELSE
                *** The direct generation does not exist to add the item.
                RETURN
             END
          END

          MATPARSE CUS  FROM SV.CUS
          MATPARSE CUSS FROM SV.CUSS
          LD(6)<1,NEW.GEN> = LD(4)
          LD(7)<1,NEW.GEN> = 'D~':LED(1)<1,DGEN>

          SV.GID = LED(12)<1,GEN>
          GEN    = NEW.GEN
          IF PRD(106) THEN
             OE.GET.DKIT.COMPS OID,GEN,SHIP.BR,PN,LDID
          END

          *** Only update the line item if there were not any errors.
          IF UPDATE.OK THEN
             GOSUB PRC.ITEM
             GOSUB UPD.LINE
             LOCATE SV.GID IN LED(12)<1> SETTING GEN ELSE GEN = 1
             DIR.COMMITTED = YES
          END
          RETURN
*-------------------------------------------------------------------------*
*** Check for what the return types should be if default not set
CHK.RET:
          IF NOT(RET.TYP) THEN
             IF NOT(LED(33)<1,GEN>) AND LED(110)<1,1> # 'B' THEN
                READV RET.TYP FROM CTRLFILE,'RETURN.GOODS.TYPE',1 ELSE RET.TYP=''
                RET.TYP  = RET.TYP<1,LED(2)<1,GEN,2>>
                TST.TYPS = 'S':AM:'F':AM:'O':AM:'R'
                RETN = 0
                IF RET.TYP THEN
                   LOCATE RET.TYP IN TST.TYPS SETTING RETN ELSE RETN = 0
                END
                IF RETN=0 THEN
                   STK.TYPS = 'R-Review':VM:'F-DeFective':VM:'S-Stock':VM:'O-Overship'
                   MENU.TABLE RET.TYP,,,1,4,15,,,STK.TYPS,'Return Type',1
                END
                RET.TYP = RET.TYP[1,1]
                IF RET.TYP = 'F' THEN RETURN
             END
          END
          RETURN
*-------------------------------------------------------------------------*
GET.REMINDER: *** Retrieve all of the product reminder messages.

          REM.MSG = ''
          HAZARD  = ''
          QBREAKS = ''
          JAVA.OE.GET.PRD.MSGS OID,GEN,QSIGN,YES,YES,REM.MSG,HAZARD,QBREAKS

          ERR.CODE = "26"

          *** Add the reminder message to the list of warnings
          IF REM.MSG # "" THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = 2:VM:REM.MSG
             KEY.LIST<ERR.POS>  = "Product Reminder Message"
          END

          *** Add the hazardous item message to the listst of warnings
          IF HAZARD # "" THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = 1:VM:HAZARD
             KEY.LIST<ERR.POS>  = 'Hazardous Material Information'
          END

          *** Add the Qty break info message to the listst of warnings
          IF QBREAKS # "" THEN
             ERR.CODE = "40"
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = 3:VM:QBREAKS
          END

          RETURN
*-------------------------------------------------------------------------*
LOG.UET:  *
          DIFF    = QS - ORD.QTY
          IF DIFF = 0 THEN RETURN
          UET.PARAMS.QTY.GET OID,GEN,LDID,QPARMS
          BEGIN CASE
          CASE DIFF > 0
             IF QPARMS<2>#'' THEN
                IF DIFF <= QPARMS<2> THEN RETURN
             END

             IF QPARMS<4>#'' THEN
                DPERC = 0
                IF ORD.QTY THEN DPERC = (DIFF/ORD.QTY)*100
                IF DPERC <= QPARMS<4> THEN RETURN
             END
          CASE OTHERWISE
             IF QPARMS<1>#'' THEN
                IF DIFF >= -QPARMS<2> THEN RETURN
             END

             IF QPARMS<3>#'' THEN
                DPERC = 0
                IF ORD.QTY THEN DPERC = -(DIFF/ORD.QTY)*100
                IF DPERC <= QPARMS<3> THEN RETURN
             END
          END CASE
          ACD = 'SCKAQ'
          IF PRD(3) = 2 THEN
             ACD = 'SCKAQN'
          END
          OID.DATA$ = ''
          DICT.COMMON = ""
          OID.DATA$<1> = OID
          OID.DATA$<2> = GEN
          OID.DATA$<3> = LDID
          OID.DATA$<4> = LED(5)<1,GEN>
          OID.DATA$<5> = PN
          UET.LOG.AUTO ACD,9,DIFF
          *** Reset DICT.COMMON. DICT.COMMON needs to be cleared for UET
          *** process.
          DICT.COMMON<1> = LED(2)<1,GEN,2>
          DICT.COMMON<2> = LED(2)<1,GEN,1>
          DICT.COMMON<3> = DATE()
          DICT.COMMON<4> = DATE()

          RETURN
*-------------------------------------------------------------------------*
CHK.CUSTOM: *** check for any custom mods that the customer  might have
            *** built to function off of the alt-? hidden hotkey


          OE.LI.GET.ADDL.CUSTOM OID,GEN,LDID,MSGS
          RETURN
*-------------------------------------------------------------------------*
CHK.SUB:  *** Check to see whether the item has substitutes or not.
          SPNS = ''
          OE.GET.SUBS OID,GEN,SPNS,STYPS
          OE.GET.CUS.SUBS ST.CN,PN,CUS.SPNS

          *** Auto select substitutes for this line item.
          IF AUTO.DISP.MSG = "Auto Select" AND SPNS<1,2>#'' THEN
             SUB.REQD = 2
          END ELSE
             *** Determine if the subs window needs to be opened based on
             *** additional sell item statuses and availability.
             IF SPNS<1,2>#'' OR CUS.SPNS THEN
                STK.TYPE = FIELD(LD(7)<1,1>,'~',1)
                IF STK.TYPE[1,1]='S' THEN STK.TYPE=''
                CALC.AVAIL AVAIL,LED(4)<1,GEN>,SHIP.BR,PN,STK.TYPE=STK.TYPE

                *** If the item is not avail and the control record is set
                *** to show the subs for items that are not avail, open it
                IF (AUTO.SUB = '1') AND (AVAIL <= 0) THEN
                   SUB.REQD = 2
                END ELSE
                   IF SUB.TYPE # '' THEN
                      SCT = DCOUNT(SPNS<1>,VM)
                      FOR SLN = 2 TO SCT
                         LOCATE STYPS<1,SLN> IN SUB.TYPE<1> SETTING JS THEN
                            SUB.REQD = 2
                            EXIT
                         END
                      NEXT SLN
                   END
                END
                IF NOT(SUB.REQD) THEN
                   SUB.REQD = 1
                END
             END
          END

          *** If there are substitutes on this item send whether the item
          *** has subs and if the substitute window needs to open for it.
          ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
          ERR.CODES<ERR.POS> = '27'
          ERR.MSGS<ERR.POS>  = SUB.REQD
          RETURN
*-------------------------------------------------------------------------*
CHK.SPLT: ** Checks to see if quantities can be split and passes back
          ** quantities if so.  Client relies on this code, host can
          ** ignore as it uses it's own logic in OE.
          IF NOT(MA(2)) THEN RETURN
          JAVA.OE.CHK.SPLT.QTYS LDID,GEN,QO,Q1,Q2, OID
          IF (Q1 AND Q2) THEN
             ERR.POS = DCOUNT(ERR.CODES,AM)+1
             ERR.CODES<ERR.POS> = 39
             ERR.MSGS<ERR.POS>  = Q1:SVM:Q2
          END
          RETURN
*-------------------------------------------------------------------------*
CHK.AUTO.PRC:   *** Check to see whether the auto price window
          *** Only check sales orders.
          IF MODE = 'S' THEN
             *** Check the customer setting first...
             BEGIN CASE
             CASE CUS(123) = 'Prompt'
                AUTO.PRC.VRF = YES
             *** If there's not a customer override use the control record.
             CASE CUS(123) = ''
                IF LAST.PRICE$ = 'Prompt' THEN
                   AUTO.PRC.VRF = YES
                END ELSE
                   AUTO.PRC.VRF = NO
                END
             *** Otherwise, do not open the window.
             CASE OTHERWISE
                AUTO.PRC.VRF = NO
             END CASE
          END ELSE
             AUTO.PRC.VRF = NO
          END

          *** If the window should open pass the note to the client.
          IF AUTO.PRC.VRF THEN
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = '30'
             ERR.MSGS<ERR.POS>  = 'Quick Price'
          END
          RETURN
*-------------------------------------------------------------------------*
CHK.LOT:  **** Check to see if detail lots need to be assigned for the item
          IF MODE # 'S'           THEN RETURN
          IF LED(6)<1,GEN> = 'B'  THEN RETURN
          IF NOT(DISP.LOT.SEL$)   THEN RETURN
          IF LD(4) > 0            THEN RETURN
          ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
          ERR.CODES<ERR.POS> = '32'
          ERR.MSGS<ERR.POS>  = 'Detail Lot'
          RETURN
*-------------------------------------------------------------------------*
CHECK.SCHEDULE: * Check to see if the line item scheduler should be opened

          *** For PO's, quantity shipped and order quantity open will be
          *** the same regardless if qty is avail or not - open the
          *** schedule screen if qty is not avail for users with only
          *** level 1 of authorization key POE.SCHEDULE
          *** If qty not avail for sales/transfers, qty shipped # ordered
          CHK.PO = NO
          IF SCHED.ON = 1 AND MODE = 'P' THEN
             STK.TYPE = FIELD(LD(7)<1,1>,'~',1)
             IF STK.TYPE[1,1] = 'S' THEN STK.TYPE = ''

             CALC.AVAIL AVAIL,DATE(),LED(2)<1,GEN,2>,LD(1),,STK.TYPE

             IF AVAIL < 0 THEN CHK.PO = YES
          END
          SCHED = (SCHED.ON=1 AND (QS#QOPEN OR CHK.PO)) OR SCHED.ON = 2

          *** Setup the message information for the client.
          BEGIN CASE
          *** Force the scheduler open for inventory overrides
          CASE SCHEDULE.ITEM
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = '33'
             ERR.MSGS<ERR.POS>  = '2'
          *** Auth level 1 handling to open the line item scheduler.
          CASE SCHED
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = '33'
             ERR.MSGS<ERR.POS>  = '1'
          END CASE

          IF MODE='S' AND QS#QOPEN THEN
             SOE.CHK.DISP.QTY OID,GEN,LDID,QS,QOPEN,RESULTS,DATA
             IF RESULTS THEN
                ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                ERR.CODES<ERR.POS> = '43'
                ERR.MSGS<ERR.POS>  = LOWER(LOWER(RESULTS)):VM:DATA
             END
          END

          RETURN
*-------------------------------------------------------------------------*
CALC.FF:  *** Calculate Freight Factor freight
          IF NOT(NUM(LD(1))) THEN RETURN
          *** They must have freight factor specified.
          FF.METH = (LED(93)<1,GEN,1>[1,1] = 'F')
          IF NOT(FF.METH) THEN RETURN
          OE.CALC.FF LD(1),LD(8)<1,GEN>,LED(2)<1,GEN,1>,FGHT
          LD(34)<1,GEN> = FGHT
          RETURN
*-------------------------------------------------------------------------*
SET.DATA: *** Setup the global order information for use.
          OID.DATA$   = ''
          DICT.COMMON = ""
          OID.DATA$<1>   = OID
          OID.DATA$<2>   = GEN
          OID.DATA$<3>   = LDID
          OID.DATA$<4>   = LED(5)<1,GEN>
          OID.DATA$<5>   = PN
          DICT.COMMON<1> = LED(2)<1,GEN,2>
          DICT.COMMON<2> = LED(2)<1,GEN,1>
          DICT.COMMON<3> = DATE()
          DICT.COMMON<4> = DATE()
          RETURN
*-------------------------------------------------------------------------*
CHK.NO.DISP.TYPS: *** check to make sure this isn't a product type
                  *** that we should not display the return goods
                  *** verification screen

          NO.DISP.TYPE = NO
          IF NODISP.TYPS THEN
             TYP.CNT = DCOUNT(NODISP.TYPS,VM)
             FOR TYP = 1 TO TYP.CNT
                LOCATE NODISP.TYPS<1,TYP> IN PRD.TYPS<1> SETTING POS THEN
                   IF PRD(3) = POS THEN NO.DISP.TYPE = YES
                END
             NEXT TYP
          END
          RETURN
*-------------------------------------------------------------------------*
LOG.ABC:  *** Log the ABC code for the event that occured.
          ABC.LOG.AUTO ACD

          RETURN
*-------------------------------------------------------------------------*
VIEW.BR.INVS: *** Verify whether to show the branch available qtys on a
              *** sales order for the other branches or not

          AVAIL    = YES
          CTRL.SET = SHOW.AVAIL[1,1]

*** If control record is set to display branch availablity when there is
*** none availalble in current shipping branch, determine first available
*** shipping date of this item.
          IF CTRL.SET = 'U' THEN
             OE.CHECK.AVAIL.ALL OID,LDID,AVAIL.DATE
             COMP.DATE     = LED(9)<1,GEN>
             IF COMP.DATE  < DATE() THEN COMP.DATE = DATE()
             IF AVAIL.DATE > COMP.DATE THEN AVAIL = NO
          END

*** If the setting is always or the item's not available and that's when
*** they want to see the other branches available quantities, set up the
*** message code for the client.
          IF CTRL.SET = 'A' OR (CTRL.SET = 'U' AND NOT(AVAIL)) THEN
             ERR.CODE           = '36'
             ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
             ERR.CODES<ERR.POS> = ERR.CODE
             ERR.MSGS<ERR.POS>  = 'Show Branch Avail'
          END
          RETURN
*-------------------------------------------------------------------------*
UPD.LINE.FGHT: ***  redistribute the line freight when a line item is
               ***  added.

          IF NOT(NEW.LD) THEN RETURN
          IF NOT(MODE = 'P') THEN RETURN
          OE.CALC.FGHT OID,GEN,FGHT
          POE.UPD.LINE.FGHT OID,GEN,FGHT
          LD.GET LDID
          MAT OLD.LD = MAT LD
          GET.ALL.PRD PRC.BR,PN,QSIGN
          RETURN
*-------------------------------------------------------------------------*
CHECK.RET:*** If we are attempting to enter a return item check to
          *** make sure there are not already positive Qty items on the
          *** order.  (This only matters if the jurisdiction code or
          *** control file item are set to use original sales order ship
          *** date to get the tax rate for the return
          RET.ERR = NO
          LLIST   = ""

          TAXCD = LED(79)<1,GEN,1>
          MATREAD TAX FROM TAXFILE,TAXCD ELSE MAT TAX=''
          IF TAX(15)<2> = '' THEN
             READ ORIG.SALE FROM CTRLFILE,'RETURN.TAX.RATE' ELSE
                ORIG.SALE = ''
             END
          END ELSE
             ORIG.SALE = TAX(15)<2>
          END
          IF ORIG.SALE THEN
             IF LED(8)<1,GEN> THEN
                LLIST = RAISE(LED(48)<1,GEN>)
             END ELSE
                LLIST = LED(49)
             END
             IF LLIST # "" THEN
                MATBUILD SAVE.LD FROM LD
                FOR LN = 1 TO DCOUNT(LLIST,VM)
                   LD.GET LLIST<1,LN>
                   ADD.MSG = NO
                   IF QO < 0 AND LD(4)+0 < 0 THEN ADD.MSG = YES
                   IF QO > 0 AND LD(4)+0 > 0 THEN ADD.MSG = YES
                   IF ADD.MSG THEN
                      MSG      = 'Taxes on returns are calculated using '
                      MSG:= 'the original sales order tax rate.'
                      MSG:=VM:'Return items and sale item cannot be on the same order'
                      ERR.POS            = DCOUNT(ERR.CODES,AM) + 1
                      ERR.CODES<ERR.POS> = 41
                      ERR.MSGS<ERR.POS>  = MSG
                      UPDATE.OK          = NO
                      FATAL.ERR          = YES
                      QO = SV.QO
                      ERR = YES
                      RET.ERR = YES
                      EXIT
                   END
                NEXT LN
                MATPARSE LD FROM SAVE.LD
             END
          END

          RETURN
!TRAVISC~03/07/12~17:26
